/*******************************************************************
* Copyright (c) 2010 BSUIR <romkisel@gmail.com>

* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:

* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
********************************************************************/

#ifndef OPTIXSCENE_H
#define OPTIXSCENE_H

#include <QGraphicsScene>
#include <QList>
#include <QStack>
#include <QMenu>
#include <QToolBar>
#include <QString>
#include <QDomElement>
#include "shadowmap.h"
#include "border.h"
#include "transparentborder.h"
#include "mirror.h"
#include "plight.h"
#include "dlight.h"

class OptixScene : public QGraphicsScene
{
    Q_OBJECT
public:
    OptixScene(QObject *prnt = 0);

    enum mode { ordinary, rotate, scale } curMode;
    enum saveMode { unnamed, named } curSaveMode;

public:
    static const int cSceneW = 1500;
    static const int cSceneH = 1500;

public slots:
    void changeDraw(const QList<QRectF> &);

    void selectItem();
    void srlRotateChange(int);
    void srlScaleChange(int);
    void srlScaleXChange(int);
    void srlScaleYChange(int);

    void deleteItems();

    void actionRotate();
    void actionScale();
    void actionToFront();
    void actionToBack();
    void actionColor();
    void actionSettings();
    void actionNew();
    void actionOpen();
    void actionSave();
    void actionSaveAs();
    void actionAbout();

public:
    void setContextMenu(QMenu *menu);
    void setToolBar(QToolBar *toolBar);
    QMenu *ContextMenu();
    void drawLigths();
    void drawDLights(DLight *light);
    void traceRay(DLight *light, QLineF line);
    void drawPShadows();
    void rotateItem(QGraphicsItem *item, int value);
    void scaleItem(QGraphicsItem *item, qreal sx, qreal sy);

    void addPLight(QPointF pos);
    void addDLight(QPointF pos);
    void addBorder(QPointF pos);
    void addBorderTriangle(QPointF pos);
    void addBorderGexagon(QPointF pos);
    void addMirror(QPointF pos);
    void addTPlate(QPointF pos);
    void addTrianglePrism(QPointF pos);
    void addConvexLens(QPointF pos);
    void addConvexLens2(QPointF pos);
    void addConcaveLens(QPointF pos);
    void addConcaveLens2(QPointF pos);
    void addRuler(QPointF pos);
    void addProtractor(QPointF pos);

    QList<Border *> getBorders();
    QList<TransparentBorder *> getTBorders();
    QList<Mirror *> getMirrors();
    QList<PLight *> getPLights();
    QList<DLight *> getDLights();

    void saveFile(QString fileName);
    bool openFile(QString fileName);

    void traverseNode(QDomNode &node);
    void loadElement(QString type, QDomNode &node);
    void loadInfo(QDomNode domNode, qreal &angle, qreal &sx, qreal &sy, QColor &color);
    void loadPolygon(QDomNode domNode, QPolygonF &poly);
    QDomElement makeInfoItem(QDomDocument &doc, QGraphicsItem *item);
    QDomElement addElement(QDomDocument &doc, QGraphicsItem *item);
    QDomElement makePolygonInfo(QDomDocument &doc, const QPolygonF &poly);
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent);
    void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
    void dropEvent(QGraphicsSceneDragDropEvent *event);
    void drawForeground(QPainter * painter, const QRectF & rect);
    void drawBackground(QPainter * painter, const QRectF & rect);

private:
    QStack<TransparentBorder *> traceStack;         //stack of refracted borders
    QGraphicsRectItem *dropRect;
    ShadowMap shadMap;
    qreal densityAir;

    QMenu *contextMenu;
    QToolBar *toolBar;

    QGraphicsItem *curSelectItem;
    QString curFile;
};

#endif // OPTIXSCENE_H
